package com.neuronbit.businessflow.intellij;

import com.google.gson.JsonArray;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.TypeRef;
import com.jayway.jsonpath.spi.json.GsonJsonProvider;
import com.jayway.jsonpath.spi.mapper.GsonMappingProvider;

import static com.neuronbit.businessflow.intellij.util.GsonUtils.gson;

/**
 * The type Json.
 */
public final class Json {
    private final String json;
    private final DocumentContext documentContext;

    /**
     * Instantiates a new Json.
     *
     * @param json the json
     */
    public Json(String json) {
        this.json = json;
        Configuration conf = Configuration.builder()
                .jsonProvider(new GsonJsonProvider(gson))
                .mappingProvider(new GsonMappingProvider(gson))
                .build();
        this.documentContext = JsonPath.using(conf).parse(json);
    }

    /**
     * Read t.
     *
     * @param <T>        the type parameter
     * @param path       the path
     * @param startClass the start class
     * @return the t
     */
    public <T> T read(String path, Class<T> startClass) {
        try {
            return documentContext.read(path, startClass);
        } catch (Exception e) {
            //ignore
            System.out.println(e.getMessage());
            return null;
        }
    }

    /**
     * Read string.
     *
     * @param path the path
     * @return the string
     */
    public String read(String path) {
        try {
            return documentContext.read(path, String.class);
        } catch (Exception e) {
            //ignore
            System.out.println(e.getMessage());
            return null;
        }
    }

    /**
     * Read t.
     *
     * @param <T>     the type parameter
     * @param path    the path
     * @param typeRef the type ref
     * @return the t
     */
    public <T> T read(String path, TypeRef<T> typeRef) {
        try {
            return documentContext.read(path, typeRef);
        } catch (Exception e) {
            //ignore
            System.out.println(e.getMessage());
            return null;
        }
    }

    /**
     * Read int integer.
     *
     * @param path the path
     * @return the integer
     */
    public Integer readInt(String path) {
        try {
            return documentContext.read(path);
        } catch (Exception e) {
            //ignore
            System.out.println(e.getMessage());
            return null;
        }
    }

    /**
     * Length int.
     *
     * @param s the s
     * @return the int
     */
    public int length(String s) {
        try {
            Object startCount = documentContext.read(s);
            if (null != startCount) {
                return ((JsonArray) startCount).size();
            } else {
                return 0;
            }
        } catch (Exception e) {
            //ignore
            System.out.println(e.getMessage());
            return 0;
        }
    }

    /**
     * Test object.
     *
     * @param path the path
     * @return the object
     */
    public Object test(String path) {
        try {
            return documentContext.read(path);
        } catch (Exception e) {
            //ignore
            System.out.println(e.getMessage());
            return null;
        }
    }

    /**
     * Array json array.
     *
     * @param path the path
     * @return the json array
     */
    public JsonArray array(String path) {
        try {
            return documentContext.read(path);
        } catch (Exception e) {
            //ignore
            System.out.println(e.getMessage());
            return null;
        }
    }
}
